import time
from typing import List

import pydantic
from fastapi import Depends
from fastapi_pagination.bases import AbstractPage
from fastapi_pagination.ext.databases import paginate
from sqlalchemy import delete, func, insert, select, update

from forward.api.admin.config import AdminConfig
from forward.api.admin.schemas.system import (
    SystemAuthRoleCreateInSchema,
    SystemAuthRoleEditInSchema,
    SystemAuthRoleOutSchema,
    SystemAuthRoleDetailOutSchema,
    SystemAuthRoleSchema,
)
from forward.dependencies.database import db
from forward.model.tables import SystemAuthRoleModel, SystemAuthAdminModel
from forward.utils.redis import RedisUtil
from forward.api.admin.service.system.auth_perm import SystemAuthPermService


class SystemAuthRoleService:
    """系统角色服务实现类"""

    async def all(self) -> List[SystemAuthRoleOutSchema]:
        """角色所有"""
        roles = await db.fetch_all(
            select(SystemAuthRoleModel).order_by(
                SystemAuthRoleModel.sort.desc(), SystemAuthRoleModel.id.desc()
            )
        )
        return [SystemAuthRoleOutSchema.model_validate(role,from_attributes=True) for role in roles]

    async def list(self) -> AbstractPage[SystemAuthRoleDetailOutSchema]:
        """角色列表"""
        query = select(SystemAuthRoleModel).order_by(
            SystemAuthRoleModel.sort.desc(), SystemAuthRoleModel.id.desc()
        )
        pager = await paginate(db, query)
        for obj in pager.lists:
            obj.member = await self.get_member_cnt(obj.id)
        return pager

    async def get_member_cnt(self, role_id: int):
        """根据角色ID获取成员数量"""
        return await db.fetch_val(
            select(func.count(SystemAuthAdminModel.id)).where(
                func.find_in_set(role_id, SystemAuthAdminModel.role_ids),
                SystemAuthAdminModel.is_delete == 0,
            )
        )

    async def detail(self, id_: int) -> SystemAuthRoleDetailOutSchema:
        """角色详情"""
        role_record = await db.fetch_one(
            select(SystemAuthRoleModel).where(SystemAuthRoleModel.id == id_).limit(1)
        )
        assert role_record, "角色已不存在!"
        role = SystemAuthRoleSchema.model_validate(role_record,from_attributes=True)
        role_id = role.id
        role_dict = role.model_dump()
        role_dict["member"] = await self.get_member_cnt(role_id)
        role_dict["menus"] = await self.auth_perm_service.select_menu_ids_by_role_id(
            [role_id]
        )
        return SystemAuthRoleDetailOutSchema(**role_dict)

    @db.transaction()
    async def add(self, create_in: SystemAuthRoleCreateInSchema):
        """新增角色"""
        assert not await db.fetch_one(
            select(SystemAuthRoleModel)
            .where(SystemAuthRoleModel.name == create_in.name.strip())
            .limit(1)
        ), "角色名称已存在!"
        role_dict = create_in.model_dump()
        role_dict["name"] = create_in.name.strip()
        
        del role_dict["menu_ids"]
        result = await db.execute(insert(SystemAuthRoleModel).values(role_dict))
        menu_ids = create_in.menu_ids or ""
        await self.auth_perm_service.batch_save_by_menu_ids(result, menu_ids)

    @db.transaction()
    async def edit(self, edit_in: SystemAuthRoleEditInSchema):
        """编辑角色"""
        assert await db.fetch_one(
            select(SystemAuthRoleModel)
            .where(SystemAuthRoleModel.id == edit_in.id)
            .limit(1)
        ), "角色已不存在!"
        assert not await db.fetch_one(
            select(SystemAuthRoleModel).where(
                SystemAuthRoleModel.id != edit_in.id,
                SystemAuthRoleModel.name == edit_in.name.strip(),
            )
        ), "角色名称已存在!"
        role_dict = edit_in.model_dump()
        role_dict["name"] = edit_in.name.strip()
        del role_dict["menu_ids"]
        await db.execute(
            update(SystemAuthRoleModel)
            .where(SystemAuthRoleModel.id == edit_in.id)
            .values(**role_dict)
        )
        await self.auth_perm_service.batch_delete_by_role_id(edit_in.id)
        menu_ids = edit_in.menu_ids or ""
        await self.auth_perm_service.batch_save_by_menu_ids(edit_in.id, menu_ids)
        await self.auth_perm_service.cache_role_menus_by_role_id(edit_in.id)

    @db.transaction()
    async def delete(self, id_: int):
        """删除角色"""
        assert await db.fetch_one(
            select(SystemAuthRoleModel).where(SystemAuthRoleModel.id == id_).limit(1)
        ), "角色已不存在!"
        assert not await db.fetch_one(
            select(SystemAuthAdminModel)
            .where(
                func.find_in_set(id_, SystemAuthAdminModel.role_ids),
                SystemAuthAdminModel.is_delete == 0,
            )
            .limit(1)
        ), "角色已被管理员使用,请先移除"
        await db.execute(
            delete(SystemAuthRoleModel).where(SystemAuthRoleModel.id == id_)
        )
        await self.auth_perm_service.batch_delete_by_role_id(id_)
        await RedisUtil.hdel(AdminConfig.backstage_roles_key, str(id_))

    def __init__(self, auth_perm_service: SystemAuthPermService):
        self.auth_perm_service: SystemAuthPermService = auth_perm_service

    @classmethod
    async def instance(
        cls,
        auth_perm_service: SystemAuthPermService = Depends(
            SystemAuthPermService.instance
        ),
    ):
        """实例化"""
        return cls(auth_perm_service)
